package com.nervenets.general.annotation;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.nervenets.general.utils.ClassUtils;
import lombok.SneakyThrows;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

public class JsonSimplifySerializer extends JsonSerializer<Object> implements ContextualSerializer {
    private Class<?> simplifyClass;

    public JsonSimplifySerializer() {
    }

    public JsonSimplifySerializer(Class<?> simplifyClass) {
        this.simplifyClass = simplifyClass;
    }

    @SneakyThrows
    @Override
    public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        if (null != simplifyClass && null != o) {
            boolean array = o instanceof Collection;
            if (array) {
                ArrayList<Object> arrayList = new ArrayList<>();
                Collection o1 = (Collection) o;
                for (Object o2 : o1) {
                    arrayList.add(ClassUtils.getDeclaredConstructor(simplifyClass, o2.getClass()).newInstance(o2));
                }
                jsonGenerator.writeObject(arrayList);
            } else {
                jsonGenerator.writeObject(ClassUtils.getDeclaredConstructor(simplifyClass, o.getClass()).newInstance(o));
            }
        } else {
            jsonGenerator.writeObject(o);
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if (beanProperty != null) {
            JsonSimplify jsonSimplify = beanProperty.getAnnotation(JsonSimplify.class);
            if (jsonSimplify == null) {
                jsonSimplify = beanProperty.getContextAnnotation(JsonSimplify.class);
            }
            if (jsonSimplify != null) {
                return new JsonSimplifySerializer(jsonSimplify.simplifyClass());
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}
